package org.geoscrape.util;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.List;

import org.geoscrape.CacheType;
import org.geoscrape.util.MaskSet.MaskEntry;

/**
 * Tools for manipulating images.
 */
public class ImageToolbox
{
	private MaskSet masks;

	public ImageToolbox(MaskSet masks)
	{
		this.masks = masks;
	}
	/**
	 * @return the masks
	 */
	public MaskSet getMasks()
	{
		return masks;
	}
	public Point getLargeIconLocation(BufferedImage input)
	{
		return findLocation(input,masks.getBigIconBorder());
	}
	public Point getSmallIconLocation(BufferedImage input)
	{
		return findLocation(input,masks.getSmallIconBorder());
	}
	
	public Point findLocation(BufferedImage input, BufferedImage mask)
	{
		// search for the mask,
		// return the mask location
		int scanWidth = input.getWidth() - mask.getWidth()+1;
		int scanHeight = input.getHeight() - mask.getHeight()+1;
		for (int x = 0; x < scanWidth; x++)
		{
			for (int y = 0; y < scanHeight; y++)
			{
				if (foundMask(x, y, input,mask))
				{
					return new Point(x, y);
				}
			}
		}
		return null;
	}

	private boolean foundMask(int left, int top, BufferedImage input,BufferedImage mask)
	{
		return maskMatches(left,top,input,mask);
	}
	
	/**
	 * Return true if the non-transparent parts of mask has the same colour as the corresponding part of input,
	 * offset with left and top.
	 * 
	 * @param left
	 * @param top
	 * @param inupt
	 * @param mask
	 * @return
	 */
	private boolean maskMatches(int left, int top,BufferedImage input, BufferedImage mask)
	{
		for(int x =0;x<mask.getWidth();x++)
		{
			for(int y = 0;y<mask.getHeight();y++)
			{
				if(isOpaque(x,y,mask))
				{
					if(mask.getRGB(x, y)!=input.getRGB(x+left, y+top))
					{
						return false;
					}
				}
			}
		}
		return true;
	}
	
	/**
	 * Check if a pixel is opaque (true) or transparent (false).
	 * 
	 * @param x
	 * @param y
	 * @param img
	 * @return
	 */
	private boolean isOpaque(int x, int y, BufferedImage img)
	{
		int px = img.getRGB(x, y);
		px &= 0xFF000000;
		return px != 0;
	}

	public BufferedImage getLargeIcon(BufferedImage input, Point loc)
	{
		return getSubImage(input,loc,20,20);
	}
	public BufferedImage getSmallIcon(BufferedImage input, Point loc)
	{
		return getSubImage(input,loc,8,8);
	}
	public BufferedImage getSubImage(BufferedImage input, Point loc, int width, int height)
	{
		// get the sub-image
		BufferedImage tmp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = tmp.createGraphics();
		g.drawImage(input, 0, 0, width, height, loc.x, loc.y, loc.x + width, loc.y + height, null);
		return tmp;
	}
	public CacheType getType(BufferedImage img, List<MaskEntry>entries)
	{
		for(MaskEntry me:entries)
		{
			if(maskMatches(0,0,img,me.getMask()))
			{
				return me.getEntry();
			}
		}
		return null;
	}
}
